package com.umakr.ax.utils;

import com.umakr.ax.core.properties.DockerModel;
import com.github.dockerjava.api.DockerClient;
import com.github.dockerjava.api.async.ResultCallback;
import com.github.dockerjava.api.command.*;
import com.github.dockerjava.api.model.BuildResponseItem;
import com.github.dockerjava.core.DockerClientBuilder;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import java.io.Closeable;
import java.io.File;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;

/**
 *
 * @author ~scl
 * @date 2017/5/22
 */
public class DockerUtil {

    protected final Log logger = LogFactory.getLog(this.getClass());
    private DockerClient client;
    private DockerModel dockerModel;

    public DockerUtil(DockerModel dockerModel){
        this.dockerModel = dockerModel;
        client = DockerClientBuilder.getInstance(this.dockerModel.getHost())
                .build();
    }

    public DockerUtil(){}

    /**
     * 根据dockerFile生成镜像，并启动容器
     * @param tag 镜像名:版本 client:0.2
     * @return containerId
     */
    public Map<String ,Object> buildImage(final String tag,String dockerFileDir) {
        final String containerName = tag.substring(0, tag.indexOf(':'));
        Container container = new Container();
        Integer maxWaitTime = 0;
        //使用内部类去存放当前容器的id 同时根据这个id判断容器是否创建完成
        File pFile = new File(dockerFileDir);
        if (!pFile.exists()) {
            pFile.mkdirs();
        }

        File file = new File(dockerFileDir + File.separator + "Dockerfile");
        BuildImageCmd bc = client.buildImageCmd();
        bc.withDockerfile(file);
        bc.withPull(true);
        bc.withTag(tag);
        bc.withBaseDirectory(pFile);
        bc.exec(new ResultCallback<BuildResponseItem>() {
            private String imageId = null;
            private String errorMsg = "";

            @Override
            public void onStart(Closeable closeable) {
                logger.info("===========onStart==========");
            }

            @Override
            public void onNext(BuildResponseItem buildResponseItem) {
                if (imageId == null) {
                    imageId = buildResponseItem.getImageId();
                }
                if (buildResponseItem.isErrorIndicated()) {
                    errorMsg += buildResponseItem.getError();
                }
            }

            @Override
            public void onError(Throwable throwable) {
                throwable.fillInStackTrace();
            }

            @Override
            public void onComplete() {

                if (!"".equals(errorMsg)) {
                    logger.error("Dockerfile error info ---> " + errorMsg);
                    container.setError(errorMsg);
                    //删除镜像
                    removeImage(imageId);
                } else {
                    //创建Container
                    try(CreateContainerCmd ccd = client.createContainerCmd(imageId);) {
                        ccd.withName(containerName);
                        CreateContainerResponse ccr = ccd.exec();
                        //启动Container
                        startContainer(ccr.getId());
                        container.setContainId(ccr.getId());
                    } catch (Exception e) {
                        logger.info(e);
                    }


                }
            }

            @Override
            public void close() throws IOException {
                // Do nothing because of X and Y.

            }
        });

        while(container.getContainId() == null && maxWaitTime < 60){
            try {
                Thread.sleep(1000);
                maxWaitTime++;
            } catch (InterruptedException e) {
                logger.error(e);
            }
        }

        Map<String ,Object> resultMap = new HashMap<>(16);
        resultMap.put("containerId",container.getContainId());
        resultMap.put("hasError",container.getError());
        return resultMap;
    }

    /**
     * 查看容器的状态 返回总共60条数据
     * @param containerId
     */
    public String statusContainer(String containerId){
        if(containerId == null) {
            return "容器Id不能为空";
        }

        try {
            return RestfulUtil.getMessage("http://"+dockerModel.getCadvisorUrl()+"/api/v1.3/docker/"+containerId);
        } catch (Exception e) {
            return "容器Id不存在";
        }
    }

    /**
     * 删除一个容器
     */
    public void startContainer(String containerId){
        //启动Container
        StartContainerCmd scd = client.startContainerCmd(containerId);
        scd.exec();
    }

    /**
     * 删除一个容器
     */
    public void unStallContainer(String containerId){
        String imageId = getImageId(containerId);

        //停止
        StopContainerCmd stop = client.stopContainerCmd(containerId);
        stop.exec();

        RemoveContainerCmd rm = client.removeContainerCmd(containerId);
        rm.exec();

        removeImage(imageId);
    }

    /**
     * 删除一个镜像
     */
    public void removeImage(String imageId){
        RemoveImageCmd rmi = client.removeImageCmd(imageId);
        rmi.exec();
    }

    /**
     * 获取镜像id
     * @param containerId
     * @return
     */
    public String getImageId(String containerId){
        InspectContainerCmd ic = client.inspectContainerCmd(containerId);
        InspectContainerResponse icr = ic.exec();
        return icr.getImageId();
    }

    class Container{
        String containId = null;
        String error = null;

        public String getContainId() {
            return containId;
        }

        public void setContainId(String containId) {
            this.containId = containId;
        }

        public String getError() {
            return error;
        }

        public void setError(String error) {
            this.error = error;
        }
    }
}
